// NewTableDlg.cpp : implementation file
//

#include "stdafx.h"
#include "TSG.h"
#include "NewTableDlg.h"
#include "NewElementDlg.h"
#include "DVBRule.h"
#include "TSGDoc.h"
#include "MainFrm.h"

static element_node* pTableRoot = NULL;


// CNewTableDlg dialog

IMPLEMENT_DYNAMIC(CNewTableDlg, CDialog)

CNewTableDlg::CNewTableDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CNewTableDlg::IDD, pParent)
	, m_szTableName(_T(""))
{
	m_hItemSelected = NULL;
	//m_pNewTable = 0;
}

CNewTableDlg::~CNewTableDlg()
{
}

void CNewTableDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_TREE_ELEMENT, m_TreeElement);
	DDX_Text(pDX, IDC_TABLE_NAME, m_szTableName);
	DDV_MaxChars(pDX, m_szTableName, 8);
}


BEGIN_MESSAGE_MAP(CNewTableDlg, CDialog)
	ON_NOTIFY(NM_RCLICK, IDC_TREE_ELEMENT, &CNewTableDlg::OnNMRClickTreeElement)
	ON_COMMAND(ID_INSERTANEWITEM_INSERTATSAMELEVEL, &CNewTableDlg::OnInsertanewitemInsertatsamelevel)
	ON_COMMAND(ID_INSERTANEWITEM_INSERTASACHILD, &CNewTableDlg::OnInsertanewitemInsertasachild)
	ON_COMMAND(ID_ELEMENTMANUPUTNATION_DELETETHISITEM, &CNewTableDlg::OnElementmanuputnationDeletethisitem)
	ON_COMMAND(ID_ELEMENTMANUPUTNATION_MODIFYTHISITEM, &CNewTableDlg::OnElementmanuputnationModifythisitem)
END_MESSAGE_MAP()


// CNewTableDlg message handlers

BOOL CNewTableDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  Add extra initialization here

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CNewTableDlg::OnNMRClickTreeElement(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: Add your control notification handler code here
	UINT nFlags;
	CPoint pt;
	GetCursorPos(&pt);
	m_TreeElement.ScreenToClient(&pt);
	m_hItemSelected = m_TreeElement.HitTest(pt,&nFlags);

	if((m_hItemSelected && (nFlags & TVHT_ONITEM))||m_TreeElement.GetCount() == 0)
	{
		CMenu menu, *pMenu, *pSubMenu;
		menu.LoadMenuW(IDR_MENU_RIGHT);
		pMenu = menu.GetSubMenu(0);
		pSubMenu = pMenu->GetSubMenu(0);
		GetCursorPos(&pt);
		if(m_TreeElement.GetCount() == 0)
		{
			pSubMenu->EnableMenuItem(1,MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
		}
		else
		{
			pSubMenu->EnableMenuItem(1,MF_BYPOSITION | MF_ENABLED);
		}

		pMenu->TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this);
	}

	*pResult = 0;
}

void CNewTableDlg::OnInsertanewitemInsertatsamelevel()
{
	// TODO: Add your command handler code here
	//if(m_hItemSelected)
	{
		CNewElementDlg dlg;
		if(IDOK == dlg.DoModal())
		{			 
			CString szName = dlg.m_szName;
			CString szNumOfBits = dlg.m_szNumOfBits;
			CString szIdentifier = dlg.m_szIndentifier;
			CString szValue = dlg.m_szValue;
			CString szText = szName+_T(": ")+szNumOfBits+_T(" ")+szIdentifier+_T(" ")+szValue;

			TVINSERTSTRUCT tvInsert;
			if(m_hItemSelected)
			{
				tvInsert.hParent = m_TreeElement.GetParentItem(m_hItemSelected);
			}
			else
			{
				tvInsert.hParent = NULL;
			}
			tvInsert.hInsertAfter = m_hItemSelected;
			tvInsert.item.mask = TVIF_TEXT;
			tvInsert.item.pszText = szText.AllocSysString();
			HTREEITEM hItem = m_TreeElement.InsertItem(&tvInsert);
			::SysFreeString(tvInsert.item.pszText);
			m_TreeElement.EnsureVisible(hItem);

			element_node* pNode = new element_node;
			if(pNode)
			{
				pNode->bProgress = 0;
				pNode->pAttribute = NULL;
				pNode->pChildNode = NULL;
				pNode->pName = NULL;
				pNode->pNextNode = NULL;
				pNode->status = 0;

				errno_t     returnValue;
				size_t      pReturnValue;
				size_t      sizeOfmbStr = 1;
				//int len = szName.GetLength()+1;
				char* pName = new char[32];			
				//returnValue = wcstombs_s(&pReturnValue, pName, szName.GetLength()*2, szName.GetBuffer(),szName.GetLength());
				returnValue = wcstombs_s(&pReturnValue, pName, 32, (LPCTSTR)szName,31);
				pName[szName.GetLength()] = '\0';
				//szName.ReleaseBuffer();
				pNode->pName = pName;
				
				if(szNumOfBits != "")
				{
					element_node* pTypeNode = new element_node;
					if(pTypeNode)
					{
						pTypeNode->bProgress = 0;
						pTypeNode->pAttribute = NULL;
						pTypeNode->pChildNode = NULL;
						pTypeNode->pName = NULL;
						pTypeNode->pNextNode = NULL;
						pTypeNode->status = 0;

						char* pType = new char[8];
						sprintf_s(pType, 5, "type");
						pType[4] = '\0';
						pTypeNode->pName = pType;

						CString attribute = szNumOfBits + szIdentifier;
						char *pAttribute = new char[16];
						//returnValue = wcstombs_s(&pReturnValue, pAttribute, attribute.GetLength()*2, attribute.GetBuffer(),attribute.GetLength());
						returnValue = wcstombs_s(&pReturnValue, pAttribute, 16, (LPCTSTR)attribute,15);
						pAttribute[attribute.GetLength()] = '\0';
						//attribute.ReleaseBuffer();
						pTypeNode->pAttribute = pAttribute;
					}
					pNode->pChildNode = pTypeNode;
				}

				if(szValue != "")
				{
					element_node* pValueNode = new element_node;
					if(pValueNode)
					{
						pValueNode->bProgress = 0;
						pValueNode->pAttribute = NULL;
						pValueNode->pChildNode = NULL;
						pValueNode->pName = NULL;
						pValueNode->pNextNode = NULL;
						pValueNode->status = 0;

						char* pValue = new char[8];
						sprintf_s(pValue, 6, "value");
						pValue[5] = '\0';
						pValueNode->pName = pValue;

						CString attribute = szValue;
						char *pAttribute = new char[16];
						//returnValue = wcstombs_s(&pReturnValue, pAttribute, attribute.GetLength()*2, attribute.GetBuffer(),attribute.GetLength());
						returnValue = wcstombs_s(&pReturnValue, pAttribute, 16, attribute,15);
						pAttribute[attribute.GetLength()] = '\0';
						//attribute.ReleaseBuffer();
						pValueNode->pAttribute = pAttribute;
					}
					if(pNode->pChildNode)
					{
						element_node* pChild = pNode->pChildNode;
						while(pChild->pNextNode != NULL)
						{
							pChild = pChild->pNextNode;
						}
						pChild->pNextNode = pValueNode;
					}
					else
					{
						pNode->pChildNode = pValueNode;
					}
				}

				if(m_hItemSelected)
				{
					element_node* pInsertAfter = (element_node*)m_TreeElement.GetItemData(m_hItemSelected);
					if(pInsertAfter)
					{
						pNode->pNextNode = pInsertAfter->pNextNode;
						pInsertAfter->pNextNode = pNode;
					}
				}
				m_TreeElement.SetItemData(hItem, (DWORD_PTR)pNode);
			}			
		}
	}
}

void CNewTableDlg::OnInsertanewitemInsertasachild()
{
	// TODO: Add your command handler code here
	if(m_hItemSelected)
	{
		BOOL bChild = FALSE;
		HTREEITEM hChildItem = m_TreeElement.GetChildItem(m_hItemSelected);
		if(hChildItem)
		{
			bChild = TRUE;
		}

		CNewElementDlg dlg;
		if(IDOK == dlg.DoModal())
		{			 
			CString szName = dlg.m_szName;
			CString szNumOfBits = dlg.m_szNumOfBits;
			CString szIdentifier = dlg.m_szIndentifier;
			CString szValue = dlg.m_szValue;
			CString szText = szName+_T(": ")+szNumOfBits+_T(" ")+szIdentifier+_T(" ")+szValue;

			TVINSERTSTRUCT tvInsert;
			tvInsert.hParent = m_hItemSelected;
			tvInsert.hInsertAfter = TVI_FIRST;
			tvInsert.item.mask = TVIF_TEXT;
			tvInsert.item.pszText = szText.AllocSysString();
			HTREEITEM hItem = m_TreeElement.InsertItem(&tvInsert);
			::SysFreeString(tvInsert.item.pszText);
			m_TreeElement.EnsureVisible(hItem);

			element_node* pNode = new element_node;
			if(pNode)
			{
				pNode->bProgress = 0;
				pNode->pAttribute = NULL;
				pNode->pChildNode = NULL;
				pNode->pName = NULL;
				pNode->pNextNode = NULL;
				pNode->status = 0;

				errno_t     returnValue;
				size_t      pReturnValue;
				size_t      sizeOfmbStr = 1;
				char* pName = new char[32];			
				//returnValue = wcstombs_s(&pReturnValue, pName, szName.GetLength()*2, szName.GetBuffer(),szName.GetLength());
				returnValue = wcstombs_s(&pReturnValue, pName, 32, (LPCTSTR)szName,31);
				pName[szName.GetLength()] = '\0';
				//szName.ReleaseBuffer();
				pNode->pName = pName;
				
				if(szNumOfBits != "")
				{
					element_node* pTypeNode = new element_node;
					if(pTypeNode)
					{
						pTypeNode->bProgress = 0;
						pTypeNode->pAttribute = NULL;
						pTypeNode->pChildNode = NULL;
						pTypeNode->pName = NULL;
						pTypeNode->pNextNode = NULL;
						pTypeNode->status = 0;

						char* pType = new char[8];
						sprintf_s(pType, 8, "type");
						pType[4] = '\0';
						pTypeNode->pName = pType;

						CString attribute = szNumOfBits + szIdentifier;
						char *pAttribute = new char[16];
						//returnValue = wcstombs_s(&pReturnValue, pAttribute, attribute.GetLength()*2, attribute.GetBuffer(),attribute.GetLength());
						returnValue = wcstombs_s(&pReturnValue, pAttribute, 16, (LPCTSTR)attribute,15);
						pAttribute[attribute.GetLength()] = '\0';
						//attribute.ReleaseBuffer();
						pTypeNode->pAttribute = pAttribute;
					}
					pNode->pChildNode = pTypeNode;
				}
				
				if(szValue != "")
				{
					element_node* pValueNode = new element_node;
					if(pValueNode)
					{
						pValueNode->bProgress = 0;
						pValueNode->pAttribute = NULL;
						pValueNode->pChildNode = NULL;
						pValueNode->pName = NULL;
						pValueNode->pNextNode = NULL;
						pValueNode->status = 0;

						char* pValue = new char[8];
						sprintf_s(pValue, 6, "value");
						pValue[5] = '\0';
						pValueNode->pName = pValue;

						CString attribute = szValue;
						char *pAttribute = new char[16];
						//returnValue = wcstombs_s(&pReturnValue, pAttribute, attribute.GetLength()*2, attribute.GetBuffer(),attribute.GetLength());
						returnValue = wcstombs_s(&pReturnValue, pAttribute, 16, (LPCTSTR)attribute,15);
						pAttribute[attribute.GetLength()] = '\0';
						//attribute.ReleaseBuffer();
						pValueNode->pAttribute = pAttribute;
					}
					if(pNode->pChildNode)
					{
						/*element_node* pChild = pNode->pChildNode;
						while(pChild->pNextNode != NULL)
						{
							pChild = pChild->pNextNode;
						}*/
						pNode->pChildNode->pNextNode = pValueNode;
					}
					else
					{
						pNode->pChildNode = pValueNode;
					}
				}

				element_node* pParent = (element_node*)m_TreeElement.GetItemData(m_hItemSelected);
				if(bChild)
				{
					element_node* pChild = (element_node*)m_TreeElement.GetItemData(hChildItem);
					pNode->pNextNode = pChild;
					pParent->pChildNode = pNode;
				}
				else
				{
					pParent->pChildNode = pNode;
				}
				m_TreeElement.SetItemData(hItem, (DWORD_PTR)pNode);
			}
		}
	}
}

static void FreeTree(element_node* pTreeRoot)
{
	if(pTreeRoot)
	{
		if(pTreeRoot->pChildNode)
		{
			FreeTree(pTreeRoot->pChildNode);
		}
		if(pTreeRoot->pNextNode)
		{
			FreeTree(pTreeRoot->pNextNode);
		}
		if(pTreeRoot->pAttribute)
		{
			delete[] pTreeRoot->pAttribute;
			pTreeRoot->pAttribute = NULL;
		}
		if(pTreeRoot->pName)
		{
			delete[] pTreeRoot->pName;
			pTreeRoot->pName = NULL;
		}
		delete pTreeRoot;
		pTreeRoot = NULL;
	}
}

void CNewTableDlg::OnElementmanuputnationDeletethisitem()
{
	// TODO: Add your command handler code here
	if(m_hItemSelected)
	{
		m_TreeElement.DeleteItem(m_hItemSelected);
		HTREEITEM hPrevious;
		hPrevious = m_TreeElement.GetNextItem(m_hItemSelected, TVGN_PREVIOUS);
		if(hPrevious)
		{
			element_node* pPrevious = (element_node*)m_TreeElement.GetItemData(hPrevious);
			element_node* pNode = (element_node*)m_TreeElement.GetItemData(m_hItemSelected);
			
			pPrevious->pNextNode = pNode->pNextNode;
			pNode->pNextNode = NULL;
			FreeTree(pNode);
		}
		else
		{
			HTREEITEM hParent = m_TreeElement.GetParentItem(m_hItemSelected);
			if(hParent)
			{
				element_node* pParent = (element_node*)m_TreeElement.GetItemData(hParent);
				element_node* pNode = (element_node*)m_TreeElement.GetItemData(m_hItemSelected);

				pParent->pChildNode = pNode->pNextNode;
				pNode->pNextNode = NULL;
				FreeTree(pNode);
			}
			else
			{
				element_node* pNode = (element_node*)m_TreeElement.GetItemData(m_hItemSelected);
				FreeTree(pNode);
			}
		}
	}
}

void CNewTableDlg::OnElementmanuputnationModifythisitem()
{
	// TODO: Add your command handler code here
	if(m_hItemSelected)
	{
		CNewElementDlg dlg;
		CString szName, szNumOfBits, szIdentifier, szValue;
		CString szText = m_TreeElement.GetItemText(m_hItemSelected);
		int n = szText.Find(':',0);
		szName = szText.Left(n);
		dlg.m_szName = szName;
		int n1 = szText.Find(' ', n);
		if(n1 > n)
		{
			int n2 = szText.Find(' ', n1+1);
			if(n2>n1)
			{
				szNumOfBits = szText.Mid(n1+1, n2-n1-1);
				dlg.m_szNumOfBits = szNumOfBits;

				int n3 = szText.Find(' ', n2+1);
				if(n3 > n2)
				{
					szIdentifier = szText.Mid(n2+1, n3-n2-1);
					dlg.m_szIndentifier = szIdentifier;			
					szValue = szText.Right(szText.GetLength()-n3-1);
					dlg.m_szValue = szValue;
				}
				else
				{
					szIdentifier = szText.Right(szText.GetLength()- n2-1);
					dlg.m_szIndentifier = szIdentifier;
				}
			}
			else
			{
				szNumOfBits = szText.Right(szText.GetLength() - n1 -1);
				dlg.m_szNumOfBits = szNumOfBits;
			}
		}

		if(dlg.DoModal() == IDOK)
		{
			szName = dlg.m_szName;
			szNumOfBits = dlg.m_szNumOfBits;
			szIdentifier = dlg.m_szIndentifier;
			szValue = dlg.m_szValue;
			szText = szName+_T(": ")+szNumOfBits+_T(" ")+szIdentifier+_T(" ")+szValue;

			m_TreeElement.SetItemText(m_hItemSelected, szText);
			element_node* pNode = (element_node*)m_TreeElement.GetItemData(m_hItemSelected);

			errno_t     returnValue;
			size_t      pReturnValue;
			size_t      sizeOfmbStr = 1;
			char* pName = new char[32];			
			//returnValue = wcstombs_s(&pReturnValue, pName, szName.GetLength()*2, szName.GetBuffer(),szName.GetLength());
			returnValue = wcstombs_s(&pReturnValue, pName, 32, (LPCTSTR)szName,31);
			pName[szName.GetLength()] = '\0';
			//szName.ReleaseBuffer();
			if(pNode->pName)
			{
				delete pNode->pName;
				pNode->pName = NULL;
			}
			pNode->pName = pName;
			
			if(szNumOfBits != "")
			{
				CString attribute = szNumOfBits + szIdentifier;
				char *pAttribute = new char[16];
				//returnValue = wcstombs_s(&pReturnValue, pAttribute, attribute.GetLength()*2, attribute.GetBuffer(),attribute.GetLength());
				returnValue = wcstombs_s(&pReturnValue, pAttribute, 16, (LPCTSTR)attribute,15);
				pAttribute[attribute.GetLength()] = '\0';
				//attribute.ReleaseBuffer();
				//get the 'type' node
				pNode = pNode->pChildNode;
				if(pNode)
				{
					if(pNode->pAttribute && strcmp(pNode->pName, "type") == 0)
					{
						delete pNode->pAttribute;
						pNode->pAttribute = NULL;
						pNode->pAttribute = pAttribute;
					}					
				}
			}

			if(szValue != "")
			{
				CString attribute = szValue;
				char *pAttribute = new char[16];
				//returnValue = wcstombs_s(&pReturnValue, pAttribute, attribute.GetLength()*2, attribute.GetBuffer(),attribute.GetLength());
				returnValue = wcstombs_s(&pReturnValue, pAttribute, 16, (LPCTSTR)attribute,15);
				pAttribute[attribute.GetLength()] = '\0';
				//attribute.ReleaseBuffer();
				pNode = pNode->pNextNode;
				if(pNode)
				{
					if(pNode->pAttribute && strcmp(pNode->pName, "value") == 0)
					{
						delete pNode->pAttribute;
						pNode->pAttribute = NULL;
						pNode->pAttribute = pAttribute;
					}					
				}
			}
		}
	}
}

void CNewTableDlg::OnOK()
{
	// TODO: Add your specialized code here and/or call the base class
	UpdateData(TRUE);

	if(m_TreeElement.GetCount()<1 && m_szTableName == "")
	{
		AfxMessageBox(_T("The Table name or content cannot be NULL!!"));
		return;
	}

	element_node* pNameNode = new element_node;
	
	if(pNameNode)
	{
		pNameNode->bProgress = 0;
		pNameNode->pAttribute = NULL;
		pNameNode->pChildNode = NULL;
		pNameNode->pName = NULL;
		pNameNode->pNextNode = NULL;
		pNameNode->status = 0;

		char* pName = new char[8];
		sprintf_s(pName, 5, "name");
		pName[4] = '\0';
		pNameNode->pName = pName;

		char* pAttribute = new char[8];
		errno_t     returnValue;
		size_t      pReturnValue;
		size_t      sizeOfmbStr = 1;
		if(pName)
		{
			//returnValue = wcstombs_s(&pReturnValue, pAttribute, m_szTableName.GetLength()*2, m_szTableName.GetBuffer(),m_szTableName.GetLength());
			returnValue = wcstombs_s(&pReturnValue, pAttribute, 8, (LPCTSTR)m_szTableName,7);
			pAttribute[m_szTableName.GetLength()] = '\0';
			//m_szTableName.ReleaseBuffer();
		}
		pNameNode->pAttribute = pAttribute;
	}

	HTREEITEM hRoot = m_TreeElement.GetRootItem();
	if(hRoot)
	{
		element_node* pRoot = (element_node*)m_TreeElement.GetItemData(hRoot);
		pNameNode->pNextNode = pRoot;
	}

	element_node* pTableNode = new element_node;
	if(pTableNode)
	{
		pTableNode->bProgress = 0;
		pTableNode->pAttribute = NULL;
		pTableNode->pChildNode = NULL;
		pTableNode->pName = NULL;
		pTableNode->pNextNode = NULL;
		pTableNode->status = 0;

		char* pName = new char[8];
		sprintf_s(pName, 8, "TABLE");
		pName[5] = '\0';

		pTableNode->pName = pName;
		pTableNode->pChildNode = pNameNode;
		CTSGDoc * pCurrentDoc =(CTSGDoc*)((CMainFrame *)AfxGetMainWnd())->GetActiveDocument();
		pCurrentDoc->AddNewTable((DWORD_PTR)pTableNode);
	}

	CDialog::OnOK();
}
